//
//  Parser.m
//  ND91U
//
//  Created by 刘澎辉 on 12/13/13.
//  Copyright (c) 2013 nd. All rights reserved.
//



#import "Parser.h"

@implementation Parser

///-------------------------------
/// @name UInt -> data
///-------------------------------

+ (void)appendUInt8:(UInt8)value
                 to:(NSMutableData *)rawData {

    [rawData appendBytes:&value length:1];
}

+ (void)appendUInt16:(UInt16)value
                  to:(NSMutableData *)rawData {

    UInt16 newValue = htons(value);

    [rawData appendBytes:&newValue length:2];
}

+ (void)appendUInt32:(UInt32)value
                  to:(NSMutableData *)rawData {

    UInt32 newValue = htonl(value);

    [rawData appendBytes:&newValue length:4];
}

+ (void)appendUInt64:(UInt64)value
                  to:(NSMutableData *)rawData {

    UInt64 newValue = __DARWIN_OSSwapInt64(value);

    [rawData appendBytes:&newValue length:8];
}

///-------------------------------
/// @name data -> UInt
///-------------------------------

+ (UInt8)parseDataToUInt8:(NSData *)data {

    const void *bytes = [data bytes];

    UInt8 value = *(UInt8 *) bytes; // 方便观察变量的值

    return value;
}

+ (UInt16)parseDataToUInt16:(NSData *)data {

    const void *bytes = [data bytes];

    UInt16 value = ntohs(*(UInt16 *) bytes);

    return value;
}

+ (UInt32)parseDataToUInt32:(NSData *)data {

    const void *bytes = [data bytes];

    UInt32 value = ntohl(*(UInt32 *) bytes);

    return value;
}

+ (UInt64)parseDataToUInt64:(NSData *)data {

    const void *bytes = [data bytes];

    UInt64 value = __DARWIN_OSSwapInt64(*(UInt64 *) bytes);

    return value;
}

///-------------------------------
/// @name data
///-------------------------------

+ (UInt8)parseDataToUInt8:(NSData *)data
                      loc:(NSUInteger *)loc {

    @try {

        NSData *subdata = [data subdataWithRange:NSMakeRange(*loc, 1)];
        UInt8 value = [self parseDataToUInt8:subdata];
        *loc += 1;

        return value;
    }
    @catch (NSException *exception) {
        return 0;
    }
}

+ (UInt16)parseDataToUInt16:(NSData *)data
                        loc:(NSUInteger *)loc {

    @try {

        NSData *subdata = [data subdataWithRange:NSMakeRange(*loc, 2)];
        UInt16 value = [Parser parseDataToUInt16:subdata];
        *loc += 2;

        return value;
    }
    @catch (NSException *exception) {
        return 0;
    }
}

+ (UInt32)parseDataToUInt32:(NSData *)data
                        loc:(NSUInteger *)loc {
    @try {

        NSData *subdata = [data subdataWithRange:NSMakeRange(*loc, 4)];
        UInt32 value = [Parser parseDataToUInt32:subdata];
        *loc += 4;

        return value;
    }
    @catch (NSException *exception) {
        return 0;
    }
}

+ (UInt64)parseDataToUInt64:(NSData *)data
                        loc:(NSUInteger *)loc {
    @try {

        NSData *subdata = [data subdataWithRange:NSMakeRange(*loc, 8)];
        UInt64 value = [Parser parseDataToUInt64:subdata];
        *loc += 8;

        return value;
    }
    @catch (NSException *exception) {
        return 0;
    }
}

+ (NSString *)parseDataToNSString:(NSData *)data
                              loc:(NSUInteger *)loc {
    @try {

        NSData *subdata = [data subdataWithRange:NSMakeRange(*loc, 2)];
        UInt16 value_len = [Parser parseDataToUInt16:subdata];
        *loc += 2;

        subdata = [data subdataWithRange:NSMakeRange(*loc, value_len)];

        // 服务器返回来的字符串，有时候结尾有0，有时候结尾没有0，
        // 所以这里统一在末尾加上一个0
        NSMutableData *valueData = [NSMutableData dataWithData:subdata];
        [valueData appendBytes:"\x00" length:1];

        NSString *value = [NSString stringWithUTF8String:[valueData bytes]];

        *loc += value_len;

        return value;
    }
    @catch (NSException *exception) {
        return @"";
    }
}

///-------------------------------
/// @name NSString -> data
///-------------------------------

+ (void)appendNSString:(NSString *)string
                    to:(NSMutableData *)rawData {

    const char *ch = [string UTF8String];

    UInt16 len = strlen(ch);

    [self appendUInt16:len
                    to:rawData];

    [rawData appendBytes:ch length:len];
}

@end
